#include "fileio.hpp"
#include <fstream>
#include <iostream>
#if defined(__APPLE__)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#include <sstream>

// 检查文件名是否合法
static bool isValidFilename(const std::string& filename) {
    if (filename.empty() || filename.length() > 240) {
        return false;
    }

    // 检查非法字符
    const std::string invalid_chars = "\\/:*?\"<>|";
    return filename.find_first_of(invalid_chars) == std::string::npos;
}

// 检查目录是否可写
static bool isDirectoryWritable(const std::string& path) {
    try {
        fs::path dir_path = path.empty() ? "." : path;
        fs::path test_file = dir_path / ".test_write";
        
        std::ofstream file(test_file);
        if (!file) return false;
        file.close();
        fs::remove(test_file);
        return true;
    } catch (const std::exception&) {
        return false;
    }
}

// 获取文件路径的目录部分
static std::string getDirectory(const std::string& filepath) {
    fs::path path(filepath);
    return path.parent_path().string();
}

// 打开文本文件并解析
bool openTextFile(const std::string& filename, Dataset& dataset) {
    std::ifstream file(filename);
    if (!file) {
        return false;
    }

    std::string line, type;
    int id, pointCount;

    while (file >> id >> type) {
        if (type == "point") {
            Point p;
            if (!(file >> p.x >> p.y)) break;
            
            PointFeature pf{id, p};
            dataset.points.push_back(pf);
            dataset.addPoint(p);
        }
        else if (type == "polyline") {
            if (!(file >> pointCount)) break;
            
            PolylineFeature pl;
            pl.id = id;
            
            for (int i = 0; i < pointCount; i++) {
                Point p;
                if (!(file >> p.x >> p.y)) break;
                pl.pointIndices.push_back(dataset.addPoint(p));
            }
            dataset.polylines.push_back(pl);
        }
        else if (type == "polygon") {
            if (!(file >> pointCount)) break;
            
            PolygonFeature pg;
            pg.id = id;
            
            for (int i = 0; i < pointCount; i++) {
                Point p;
                if (!(file >> p.x >> p.y)) break;
                pg.pointIndices.push_back(dataset.addPoint(p));
            }
            dataset.polygons.push_back(pg);
        }
    }

    return true;
}

// 保存为二进制文件
bool saveToFiles(const std::string& baseFilename, const Dataset& dataset) {
    // 检查数据集
    if (dataset.allPoints.empty()) {
        std::cerr << "错误：没有数据可以保存\n";
        return false;
    }

    // 检查文件名是否合法
    if (!isValidFilename(baseFilename)) {
        std::cerr << "错误：文件名包含非法字符\n";
        return false;
    }

    // 检查目录是否可写
    std::string directory = getDirectory(baseFilename);
    if (!directory.empty() && !isDirectoryWritable(directory)) {
        std::cerr << "错误：目录 " << directory << " 不可写\n";
        return false;
    }

    try {
        // 保存点文件
        {
            std::ofstream file(baseFilename + POINT_FILE_SUFFIX, 
                             std::ios::binary | std::ios::out);
            if (!file) {
                std::cerr << "错误：无法创建点文件\n";
                return false;
            }

            int count = static_cast<int>(dataset.allPoints.size());
            file.write(reinterpret_cast<const char*>(&count), sizeof(count));
            file.write(reinterpret_cast<const char*>(dataset.allPoints.data()), 
                      count * sizeof(Point));
        }

        // 保存线文件
        {
            std::ofstream file(baseFilename + POLYLINE_FILE_SUFFIX, 
                             std::ios::binary | std::ios::out);
            if (!file) {
                std::cerr << "错误：无法创建线文件\n";
                return false;
            }

            int count = static_cast<int>(dataset.polylines.size());
            file.write(reinterpret_cast<const char*>(&count), sizeof(count));
            
            for (const auto& pl : dataset.polylines) {
                file.write(reinterpret_cast<const char*>(&pl.id), sizeof(pl.id));
                int pointCount = static_cast<int>(pl.pointIndices.size());
                file.write(reinterpret_cast<const char*>(&pointCount), sizeof(pointCount));
                file.write(reinterpret_cast<const char*>(pl.pointIndices.data()), 
                          pointCount * sizeof(int));
            }
        }

        // 保存面文件
        {
            std::ofstream file(baseFilename + POLYGON_FILE_SUFFIX, 
                             std::ios::binary | std::ios::out);
            if (!file) {
                std::cerr << "错误：无法创建面文件\n";
                return false;
            }

            int count = static_cast<int>(dataset.polygons.size());
            file.write(reinterpret_cast<const char*>(&count), sizeof(count));
            
            for (const auto& pg : dataset.polygons) {
                file.write(reinterpret_cast<const char*>(&pg.id), sizeof(pg.id));
                int pointCount = static_cast<int>(pg.pointIndices.size());
                file.write(reinterpret_cast<const char*>(&pointCount), sizeof(pointCount));
                file.write(reinterpret_cast<const char*>(pg.pointIndices.data()), 
                          pointCount * sizeof(int));
            }
        }

        return true;
    }
    catch (const std::exception& e) {
        std::cerr << "错误：保存文件时发生异常：" << e.what() << "\n";
        return false;
    }
} 